import pygame
import random as rd
from dataclasses import dataclass
#import time
import traceback
import os
import pygame.freetype
import psutil

pygame.init()
_VERSION_ = '1.0.0.Alpha_23w04a'

# 2023/05/27
_VERSION_ = '1.1.5-Beta_23w05a'# bedwar, player & 3 enemy, infohud
_VERSION_ = '1.1.6-Release' # restart game, kill/died info
_VERSION_ = '1.2-Release' # 修改重启和炸弹更新区块逻辑 
_VERSION_ = '1.2.1-Release' # 修复实体击杀数和复活数显示bug

# 2023/05/28
_VERSION_ = '1.2.2-Beta' # 修复实体击杀数和复活数显示bug
_VERSION_ = '1.3' # 添加mod, 可以修改配置, 函数。
_VERSION_ = '1.3.1-Release' # ...
_VERSION_ = '1.4.1' #添加渲染器和着色器
_VERSION_ = '1.5-Beta' #添加更多mod
_VERSION_ = '1.5.1' #enemy set blocks
_VERSION_ = '1.6.1' #添加时间计算
_VERSION_ = '1.6.2' #修复少量bug

# 2023/05/29
_VERSION_ = '1.6.3 - 1.7' # add Iris mod,修改enemy颜色区别， 添加1.7部分内容（传送，按WASD往四个方向移动5m）,printlib
_VERSION_ = '1.6.4' # 修复开始界面显示bug，-y方向方块无法破坏的bug
_VERSION_ = '1.6.5' # 修复infohud显示不全bug

# 2023/06/08
_VERSION_ = '1.7' # 修改printlib, cfg, 加入暂停功能
_VERSION_ = '1.7.1' # fix up some bugs in v1.7.
_VERSION_ = '1.7.2' # *** 修改炸弹计算逻辑 ***

# 2023/06/12
_VERSION_ = '1.7.3' # fix up render bugs, 加入简化输出信息选项, 暂停恢复后清除暂停消息字幕
# 2023/06/12 - 2023/06/13
_VERSION_ = '1.7.4' # add TNT
_VERSION_ = '1.7.5' # 增加事件提示, 修复TNT的bug
_VERSION_ = '1.7.6' # 修复分数增加减少不正确的bug, 增大enemy投掷TNT的范围, 增加TNT爆炸后环境的渲染
_VERSION_ = '1.7.7' # 修改玩家面对方向改变的逻辑, 不用移动也可改变朝向(player.facing)

# 2023/06/14
_VERSION_ = '1.7.8' # add TitleBar, 修改事件提示(add tip to capacity), 实现分散敌人的功能, 加入纯GUI模式
_VERSION_ = '1.7.9' # 可修改FPS
_VERSION_ = '1.7.10'# add Jade.py, changeable resource, 炸弹爆炸时间与fps无关

# *** ***  1.7:战斗更新  *** *** #
# *** ***  1.8:AI更新  *** *** #

# 2023/06/18
_VERSION_ = '1.7.11' # 修改部分AI, 敌人有更高几率寻找床(?未实现)和玩家, 加快分数增加速度 (including 1.8), add vsync mode 
                    # plan:TNTBreakBlocks
# 2023/06/19
_VERSION_ = '1.8' #在enemy溢出时报错, 取消胜利后的暂停, 欢迎界面显示语句(只有第一次进入时显示), 修复因末影珍珠可能导致的出界问题
_VERSION_ = '1.8.1' # 每次进入开始界面更新欢迎语句, 命令行输出事件消息受config控制, UI界面事件提醒更清楚(TitleBarPrint)
_VERSION_ = '1.8.2' # 增加对CPU和内存的显示
_VERSION_ = '1.8.3' # 增强AI, enemy不会往一些危险的地方移动
_VERSION_ = '1.8.4' # 减小enemy远离player时放置炸弹的概率, TNT break block, TNT爆炸时间缩短, 提高投掷TNT所需积分, TNT爆炸范围增大
        # 1.9内容: ice thorn cold and slow effect

# *** ***  1.9:状态效果更新  *** *** #
# 2023/06/20
_VERSION_ = '1.9' #修复重生时slow状态无法正常清除的bug, 加入shield
_VERSION_ = '1.9.1' # 修复shield功能不正常的bug, 加入状态指示器, 修复提示信息显示重叠的bug 

"""
1格: 45x45 60x60
map: 27x20 20x15
using 60x60 & 20x15.

  0: 1 2 3 4 ... ... 15 16 17 18 19   (3, 16)
0
:
1
2
3
.
.
.
11
12
13
14


(3, 11)

"""

screen = pygame.display.set_mode((1500, 900))
pygame.display.set_caption(f'({rd.randint(1200, 1999)},{rd.randint(800, 999)})QBomb Game {_VERSION_}')
f = pygame.font.Font('C:/Windows/Fonts/simhei.ttf',0x0e)
fps = pygame.time.Clock()

@dataclass
class NewVersionTip:
    isNewTry: bool = False
    string  :  str = '该版本包含1.9版本部分新内容。'
Map = []

def ftps():
    return pygame.time.get_ticks()
def cint(c):
    return c if type(c) is int else int(c)
def prob(p):
    return rd.randint(0, 100) < p

_MODS_COUNT_ = 0
import mods.CrystalLib
mods.CrystalLib.printm('Loading mod: crystal')
mods.CrystalLib.inits(fps, _VERSION_)
_MODS_COUNT_ += 1
mods.CrystalLib.printm(f'Load version: {_VERSION_}', True)
#print()
import mods.cfg
mods.CrystalLib.printm('Loading mod: cfg')
_MODS_COUNT_ += 1
#import Shaders.blockworld as bw
#printm('Loading mod: Shaders')
#mods.CrystalLib.printm(f'Loading shader: {bw.Shader_name()}')
#_MODS_COUNT_ += 1
import mods.Maplib
mods.Maplib.inits()
_MODS_COUNT_ += 1
import mods.EntityLib
mods.EntityLib.inits()
_MODS_COUNT_ += 1
import mods.printlib
mods.printlib.inits(screen)
_MODS_COUNT_ += 1
import mods.Iris
mods.Iris.inits(screen)
_MODS_COUNT_ += 1

def printm(m, g = False):
    #print(f'[{time.ctime()[11:-5]}] [INFO] {m}')
    mods.CrystalLib.printm(m, g)

WARN_TOTAL = 0
def print_warning(w):
    global WARN_TOTAL
    WARN_TOTAL += 1
    mods.CrystalLib.print_warning(w)
    if WARN_TOTAL >= 16:
        raise ValueError('[WARN COUNTER]: more than 8 warning or error occured.')
    """print(f'[{time.ctime()[11:-5]}] [WARN/ERROR] {w}')
    WARN_TOTAL += 1
    if WARN_TOTAL >= 10:
        raise ValueError('[WARN COUNTER]: more than 60 warning or error.')
    """

#printm(f'Load version: {_VERSION_}', True)

@dataclass
class Bomb:
    x     : int = 0
    y     : int = 0
    power : int = 2
    Time  : int = 2_200  #44 + 16    # tps 50, 1s = 20 tick, record Time = ftps() + 44
    belong: int = 0
    color : tuple = (255, 90, 60)  #(0, 0xff, 0)
    ID    : int = 4
    xadd  : int = 0
    xsub  : int = 0
    yadd  : int = 0
    ysub  : int = 0
    #ctype : str = 'bomb'

@dataclass
class bbs:
    x:int = 0
    y:int = 0
    color:tuple = (255,90,60)
    ID:int = 5
    towards : int = 1 # 1: n-s(y), 2: w-e(x)
    
Void = 0
Soft = 1
Hard = 2
Bed  = 3
BB   = 4
BB2  = 5
def reLoad():
    global Map
    Map = mods.Maplib.reLoad_bedwar_0()

def draw_block(x, y, dtype):
    # x=1~20,  y=1~15
    mods.Iris.draw_block(x, y, dtype, screen)
    

blist = []
def hasb(x, y):
    # has bomb?
    if blist == []:
        return False
    for bs in blist:
        if bs.x == x and bs.y == y:
            return True
    return False
def Draw_BombAround(bs):
    for x in range(max(0, bs.x - bs.power + 1), min(bs.x + bs.power, 20)):
        for y in range(max(0, bs.y - bs.power + 1), min(bs.y + bs.power, 15)):
            mods.Iris.draw_block(x, y, Map[y][x])
def MovBomb(pl, e1, e2, e3, isOnlyRender = False):
    global blist
    # draw environment/circumstance
    for bs in blist:
        Draw_BombAround(bs)
    bli = []
    for bs in blist:
        #if not isOnlyRender:
        #    bs.Time -= 1
        
        if ftps() < bs.Time:
            mods.Iris.draw_item(bs)
            bli.append(bs)
        elif ftps() - bs.Time < 9_00:
            # Bbbbbbbbbbbbb!!!
            colour = None
            if bs.belong == 0:
                colour = (0, 230, 252) # player
            elif bs.belong == 1:
                colour = (255, 6, 255)
            elif bs.belong == 2:
                colour = (0xfd, 0xe3, 0x02)
            elif bs.belong == 3:
                colour = (0xc5, 0xfb, 0x46)
            
            mods.Iris.draw_item(bbs(x = bs.x, y = bs.y, color = colour, ID = 5, towards = 0))
            if pl.x == bs.x and pl.y == bs.y and pl.health > 0:
                if bs.belong == 0:
                    if mods.cfg.FriendFire:
                        pl.health = 0
                else:
                    if bs.belong == 1:
                        e1.kill += 1
                        e1.goal += 1
                    elif bs.belong == 2:
                        e2.kill += 1
                        e2.goal += 1
                    elif bs.belong == 3:
                        e3.kill += 1
                        e3.goal += 1
            if e1.x == bs.x and e1.y == bs.y and e1.health > 0:
                if bs.belong == 0:
                    e1.health = 0
                    pl.kill += 1
                    pl.goal += 1
                else:
                    if mods.cfg.FriendFire:
                        e1.health = 0
            if e2.x == bs.x and e2.y == bs.y and e2.health > 0:
                if bs.belong == 0:
                    e2.health = 0
                    pl.kill += 1
                    pl.goal += 1
                else:
                    if mods.cfg.FriendFire:
                        e2.health = 0
            if e3.x == bs.x and e3.y == bs.y and e3.health > 0:
                if bs.belong == 0:
                    e3.health = 0
                    pl.kill += 1
                    pl.goal += 1
                else:
                    if mods.cfg.FriendFire:
                        e3.health = 0
            
            for bp in range(1, bs.power if bs.xadd == 0 else bs.xadd):
                if bs.x + bp > 19:
                    break
                if Map[bs.y][bs.x + bp] == Void:
                    mods.Iris.draw_item(bbs(x = bs.x + bp, y = bs.y, color = colour, ID = 5, towards = 2))
                if e1.x == bs.x+bp and e1.y == bs.y and e1.health > 0:
                    if 1 <= bs.belong <= 3:
                        if mods.cfg.FriendFire:
                            e1.health = 0
                    else:
                        e1.health = 0
                        pl.kill += 1
                        pl.goal += 1
                if e2.x == bs.x+bp and e2.y == bs.y and e2.health > 0:
                    if 1 <= bs.belong <= 3:
                        if mods.cfg.FriendFire:
                            e2.health = 0
                    else:
                        e2.health = 0
                        pl.kill += 1
                        pl.goal += 1
                if e3.x == bs.x+bp and e3.y == bs.y and e3.health > 0:
                    if 1 <= bs.belong <= 3:
                        if mods.cfg.FriendFire:
                            e3.health = 0
                    else:
                        e3.health = 0
                        pl.kill += 1
                        pl.goal += 1
                if pl.x == bs.x+bp and pl.y == bs.y and pl.health > 0:
                    if bs.belong == 0:
                        if mods.cfg.FriendFire:
                            pl.health = 0
                    else:
                        pl.health = 0
                        if bs.belong == 1:
                            e1.kill += 1
                            e1.goal += 1
                        elif bs.belong == 2:
                            e2.kill += 1
                            e2.goal += 1
                        elif bs.belong == 3:
                            e3.kill += 1
                            e3.goal += 1
                    #pl.died += 1
                
                if Map[bs.y][bs.x + bp] == Soft:
                    Map[bs.y][bs.x + bp] = Void
                    bs.xadd = bp + 1
                    break
                elif Map[bs.y][bs.x + bp] == Hard:
                    bs.xadd = bp + 1
                    break
                elif Map[bs.y][bs.x + bp] == Bed:
                    if bs.belong == 0:
                        if bs.y < 10 and bs.x+bp < 10:
                            Map[bs.y][bs.x + bp] = Void
                    else:
                        if bs.y > 9 and bs.x > 9:
                            Map[bs.y][bs.x + bp] = Void
                    bs.xadd = bp + 1
                    break
                
                #elif Map[pl.by][pl.bx + bp] == BB:
                #    break
            for bp in range(1, bs.power if bs.xsub == 0 else bs.xsub):
                if bs.x - bp < 0:
                    break
                if Map[bs.y][bs.x - bp] == Void:
                    mods.Iris.draw_item(bbs(x = bs.x-bp, y = bs.y, color = colour, ID = 5, towards = 2))
                if e1.x == bs.x-bp and e1.y == bs.y and e1.health > 0:
                    if 1 <= bs.belong <= 3:
                        if mods.cfg.FriendFire:
                            e1.health = 0
                    else:
                        e1.health = 0
                        pl.kill += 1
                        pl.goal += 1
                if e2.x == bs.x-bp and e2.y == bs.y and e2.health > 0:
                    if 1 <= bs.belong <= 3:
                        if mods.cfg.FriendFire:
                            e2.health = 0
                    else:
                        e2.health = 0
                        pl.kill += 1
                        pl.goal += 1
                if e3.x == bs.x-bp and e3.y == bs.y and e3.health > 0:
                    if 1 <= bs.belong <= 3:
                        if mods.cfg.FriendFire:
                            e3.health = 0
                    else:
                        e3.health = 0
                        pl.kill += 1
                        pl.goal += 1
                if pl.x == bs.x-bp and pl.y == bs.y and pl.health > 0:
                    if bs.belong == 0:
                        if mods.cfg.FriendFire:
                            pl.health = 0
                    else:
                        pl.health = 0
                        if bs.belong == 1:
                            e1.kill += 1
                            e1.goal += 1
                        elif bs.belong == 2:
                            e2.kill += 1
                            e2.goal += 1
                        elif bs.belong == 3:
                            e3.kill += 1
                            e3.goal += 1
                    #pl.died += 1
                
                if Map[bs.y][bs.x - bp] == Soft:
                    Map[bs.y][bs.x - bp] = Void
                    bs.xsub = bp + 1
                    break
                elif Map[bs.y][bs.x - bp] == Hard:
                    bs.xsub = bp + 1
                    break
                elif Map[bs.y][bs.x - bp] == Bed:
                    if bs.belong == 0:
                        if bs.y < 10 and bs.x - bp < 10:
                            Map[bs.y][bs.x - bp] = Void
                    else:
                        if bs.y > 9 and bs.x > 9:
                            Map[bs.y][bs.x - bp] = Void
                    bs.xadd = bp + 1
                    break
                #elif Map[pl.by][pl.bx - bp] == BB:
                #    break
            
            for bp in range(1, bs.power if bs.yadd == 0 else bs.yadd):
                if bs.y + bp > 14:
                    break
                if Map[bs.y + bp][bs.x] == Void:
                    mods.Iris.draw_item(bbs(x = bs.x, y = bs.y + bp, color = colour, ID = 5, towards = 1))
                if e1.y == bs.y+bp and e1.x == bs.x and e1.health > 0:
                    if 1 <= bs.belong <= 3:
                        if mods.cfg.FriendFire:
                            e1.health = 0
                    else:
                        e1.health = 0
                        pl.kill += 1
                        pl.goal += 1
                if e2.y == bs.y+bp and e2.x == bs.x and e2.health > 0:
                    if 1 <= bs.belong <= 3:
                        if mods.cfg.FriendFire:
                            e2.health = 0
                    else:
                        e2.health = 0
                        pl.kill += 1
                        pl.goal += 1
                if e3.y == bs.y+bp and e3.x == bs.x and e3.health > 0:
                    if 1 <= bs.belong <= 3:
                        if mods.cfg.FriendFire:
                            e3.health = 0
                    else:
                        e3.health = 0
                        pl.kill += 1
                        pl.goal += 1
                if pl.y == bs.y+bp and pl.x == bs.x and pl.health > 0:
                    if bs.belong == 0:
                        if mods.cfg.FriendFire:
                            pl.health = 0
                    else:
                        pl.health = 0
                        if bs.belong == 1:
                            e1.kill += 1
                            e1.goal += 1
                        elif bs.belong == 2:
                            e2.kill += 1
                            e2.goal += 1
                        elif bs.belong == 3:
                            e3.kill += 1
                            e3.goal += 1
                    #pl.died += 1
                
                if Map[bs.y + bp][bs.x] == Soft:
                    Map[bs.y + bp][bs.x ] = Void
                    bs.yadd = bp + 1
                    break
                elif Map[bs.y + bp][bs.x ] == Hard:
                    bs.yadd = bp + 1
                    break
                elif Map[bs.y + bp][bs.x ] == Bed:
                    if bs.belong == 0:
                        if bs.y + bp < 10 and bs.x < 10:
                            Map[bs.y + bp][bs.x] = Void
                    else:
                        if bs.y + bp > 9 and bs.x > 9:
                            Map[bs.y + bp][bs.x] = Void
                    bs.xadd = bp + 1
                    break
                #elif Map[pl.by + bp][pl.bx ] == BB:
                #    break
            for bp in range(1, bs.power if bs.ysub == 0 else bs.ysub):
                if bs.y - bp < 0:
                    break
                if Map[bs.y - bp ][bs.x] == Void:
                    mods.Iris.draw_item(bbs(x = bs.x, y = bs.y - bp, color = colour, ID = 5, towards = 1))
                if e1.y == bs.y-bp and e1.x == bs.x and e1.health > 0:
                    if 1 <= bs.belong <= 3:
                        if mods.cfg.FriendFire:
                            e1.health = 0
                    else:
                        e1.health = 0
                        pl.kill += 1
                        pl.goal += 1
                if e2.y == bs.y-bp and e2.x == bs.x and e2.health > 0:
                    if 1 <= bs.belong <= 3:
                        if mods.cfg.FriendFire:
                            e2.health = 0
                    else:
                        e2.health = 0
                        pl.kill += 1
                        pl.goal += 1
                if e3.y == bs.y-bp and e3.x == bs.x and e3.health > 0:
                    if 1 <= bs.belong <= 3:
                        if mods.cfg.FriendFire:
                            e1.health = 0
                    else:
                        e3.health = 0
                        pl.kill += 1
                        pl.goal += 1
                if pl.y == bs.y-bp and pl.x == bs.x and pl.health > 0:
                    if bs.belong == 0:
                        if mods.cfg.FriendFire:
                            pl.health = 0
                    else:
                        pl.health = 0
                        if bs.belong == 1:
                            e1.kill += 1
                            e1.goal += 1
                        elif bs.belong == 2:
                            e2.kill += 1
                            e2.goal += 1
                        elif bs.belong == 3:
                            e3.kill += 1
                            e3.goal += 1
                    #pl.died += 1
                
                if Map[bs.y - bp][bs.x] == Soft:
                    Map[bs.y - bp][bs.x ] = Void
                    bs.ysub = bp + 1
                    break
                elif Map[bs.y - bp][bs.x ] == Hard:
                    bs.ysub = bp + 1
                    break
                elif Map[bs.y - bp][bs.x ] == Bed:
                    if bs.belong == 0:
                        if bs.y - bp < 10 and bs.x < 10:
                            Map[bs.y - bp][bs.x] = Void
                    else:
                        if bs.y - bp > 9 and bs.x > 9:
                            Map[bs.y - bp][bs.x] = Void
                    bs.xadd = bp + 1
                    break
                #elif Map[pl.by - bp][pl.bx ] == BB:
                #    break
            Map[bs.y][bs.x] = Void
            bli.append(bs)
        else:
            # bomb blast finish. Clear it.
            if bs.belong == 0:
                pl.capacity += 1
            elif bs.belong == 1:
                e1.capacity += 1
            elif bs.belong == 2:
                e2.capacity += 1
            elif bs.belong == 3:
                e3.capacity += 1
            else:
                print_warning('Unrecognized identification: during bomb clearance')
    blist = bli

def EulaDis(x, y, a, b):
    return ((x - a) ** 2 + (y - b) ** 2) ** (1 / 2)
def MhtDis(x, y, a, b):
    return abs(abs(x - a) + abs(y - b))

TNTList = []
@dataclass
class TNT():
    x      : int = 0
    y      : int = 0
    belong : int = 0
    ID     : int = 6
    Time   : int = 1_600 + ftps()  # tps 20, 2.4s
def MovTNT(pl, e1, e2, e3):
    global TNTList
    tli = []
    for t in TNTList:
        #t.Time -= 1
        
        if ftps() >= t.Time:
            # Booooooooooooooooomb !!!
            
            # break blocks
            if mods.cfg.EnableTNTBreakBlock == True:
                """
                if Map[t.y][t.x] == Bed:
                    pass
                elif Map[t.y][t.x] == Hard:
                    Ellipsis
                elif Map[t.y][t.x] != Void:
                    Map[t.y][t.x] == Void
                else:
                    for x in range(1, mods.cfg.TNTPower + 1):
                        if t.x + x > 19:
                            break
                        if Map[t.y][t.x + x] == Void:
                            continue
                        elif Map[t.y][t.x + x] == Bed:
                            break
                        elif Map[t.y][t.x + x] == Hard:
                            break
                        else:
                            Map[t.y][t.x + x] = Void
                            break
                    for x in range(1, mods.cfg.TNTPower + 1):
                        if t.x - x < 0:
                            break
                        if Map[t.y][t.x - x] == Void:
                            continue
                        elif Map[t.y][t.x - x] == Bed:
                            break
                        elif Map[t.y][t.x - x] == Hard:
                            break
                        else:
                            Map[t.y][t.x - x] = Void
                            break
                    for x in range(1, mods.cfg.TNTPower + 1):
                        if t.y + x > 14:
                            break
                        if Map[t.y + x][t.x] == Void:
                            continue
                        elif Map[t.y + x][t.x] == Bed:
                            break
                        elif Map[t.y + x][t.x] == Hard:
                            break
                        else:
                            Map[t.y + x][t.x] = Void
                            break
                    for x in range(1, mods.cfg.TNTPower + 1):
                        if t.y - x < 0:
                            break
                        if Map[t.y - x][t.x] == Void:
                            continue
                        elif Map[t.y - x][t.x] == Bed:
                            break
                        elif Map[t.y - x][t.x] == Hard:
                            break
                        else:
                            Map[t.y - x][t.x] = Void
                            break
                    """
                if mods.cfg.UseEulaDistance:
                    for x in range(max(t.x-mods.cfg.TNTPower, 0), min(t.x + mods.cfg.TNTPower + 1, 20)):
                        for y in range(max(t.y -mods.cfg.TNTPower, 0), min(t.y + mods.cfg.TNTPower + 1, 15)):
                            if Map[y][x] == Soft and prob(50) and EulaDis(t.x, t.y, x, y) <= mods.cfg.TNTPower:
                                Map[y][x] = Void
                                draw_block(x, y, Map[y][x])
                else:
                    for x in range(max(t.x -mods.cfg.TNTPower, 0), min(t.x + mods.cfg.TNTPower + 1, 20)):
                        for y in range(max(t.y -mods.cfg.TNTPower, 0), min(t.y + mods.cfg.TNTPower + 1, 15)):
                            if Map[y][x] == Soft and prob(60):
                                Map[y][x] = Void
                                draw_block(x, y, Map[y][x])
            else:
                Ellipsis
            
            # hit entities
            draw_block(t.x, t.y, Map[t.y][t.x])
            if mods.cfg.UseEulaDistance:
                if EulaDis(t.x, t.y, pl.x, pl.y) <= mods.cfg.TNTPower:
                    if t.belong == 0:
                        if mods.cfg.FriendFire == True:
                            pl.health = 0
                    else:
                        pl.health = 0
                        if t.belong == 1:
                            e1.kill += 1
                            e1.goal += 1
                        elif t.belong == 2:
                            e2.kill += 1
                            e2.goal += 1
                        elif t.belong == 3:
                            e3.kill += 1
                            e3.goal += 1
                if EulaDis(t.x, t.y, e1.x, e1.y) <= mods.cfg.TNTPower:
                    if 1 <= t.belong <= 3:
                        if mods.cfg.FriendFire:
                            e1.health = 0
                    else:
                        e1.health = 0
                        pl.kill += 1
                        pl.goal += 1
                if EulaDis(t.x, t.y, e2.x, e2.y) <= mods.cfg.TNTPower:
                    if 1 <= t.belong <= 3:
                        if mods.cfg.FriendFire:
                            e2.health = 0
                    else:
                        e2.health = 0
                        pl.kill += 1
                        pl.goal += 1
                if EulaDis(t.x, t.y, e3.x, e3.y) <= mods.cfg.TNTPower:
                    if 1 <= t.belong <= 3:
                        if mods.cfg.FriendFire:
                            e3.health = 0
                    else:
                        e3.health = 0
                        pl.kill += 1
                        pl.goal += 1
            else:
                # Manhattan distance
                if MhtDis(t.x, t.y, pl.x, pl.y) <= mods.cfg.TNTPower:
                    if t.belong == 0:
                        if mods.cfg.FriendFire == True:
                            pl.health = 0
                    else:
                        pl.health = 0
                        if t.belong == 1:
                            e1.kill += 1
                            e1.goal += 1
                        elif t.belong == 2:
                            e2.kill += 1
                            e2.goal += 1
                        elif t.belong == 3:
                            e3.kill += 1
                            e3.goal += 1
                if MhtDis(t.x, t.y, e1.x, e1.y) <= mods.cfg.TNTPower:
                    if 1 <= t.belong <= 3:
                        if mods.cfg.FriendFire:
                            e1.health = 0
                    else:
                        e1.health = 0
                        pl.kill += 1
                        pl.goal += 1
                if MhtDis(t.x, t.y, e2.x, e2.y) <= mods.cfg.TNTPower:
                    if 1 <= t.belong <= 3:
                        if mods.cfg.FriendFire:
                            e2.health = 0
                    else:
                        e2.health = 0
                        pl.kill += 1
                        pl.goal += 1
                if MhtDis(t.x, t.y, e3.x, e3.y) <= mods.cfg.TNTPower:
                    if 1 <= t.belong <= 3:
                        if mods.cfg.FriendFire:
                            e3.health = 0
                    else:
                        e3.health = 0
                        pl.kill += 1
                        pl.goal += 1
        else:
            #t.Time -= 1
            tli.append(t)
    TNTList = tli



@dataclass
class IceThorn: # reach: 3 blocks
    x : int
    y : int
    direct: str
    Time : int  # NOT tps !!! 20tps, [0, 9] (9, 29] [20, 29)  
@dataclass
class IceThornToDraw:
    x : int
    y : int
    state : int = 2
    ID : int = 7

icelist = []
def movIceThorn(entities, isOnlyRender = False):
    global icelist
    if icelist == []:
        return;
    ice_new = []
    for ic in icelist:
        if ic.Time < 39:
            if not isOnlyRender:
                ic.Time += 1
            if ic.direct == 'east':
                xn = ic.x
                for x in range(0, 3):
                    xn = ic.x + x
                    if not 0 <= xn <= 19:
                        break
                    draw_block(xn, ic.y, Map[ic.y][xn])
                    if ic.Time<= 9:
                        if ic.Time - cint(x*3) >= 2:
                            mods.Iris.draw_item(IceThornToDraw(xn, ic.y, 2, 7))
                        elif ic.Time - cint(x*3) == 1:
                            mods.Iris.draw_item(IceThornToDraw(xn, ic.y, 1, 7))
                        elif ic.Time - cint(x*3) == 0:
                            mods.Iris.draw_item(IceThornToDraw(xn, ic.y, 0, 7))
                        else:
                            pass
                    elif 9 <= ic.Time < 39:
                        mods.Iris.draw_item(IceThornToDraw(xn, ic.y, 2, 7))
                    
                    #if xn > 19 or Map[ic.y][xn] != Void:
                    #    break
                    for en in entities:
                        if en.x == xn and en.y == ic.y:
                            en.frozen = True
            elif ic.direct == 'west':
                xn = ic.x
                for x in range(0, 3):
                    xn = ic.x - x
                    if not 0 <= xn <= 19:
                        break
                    draw_block(xn, ic.y, Map[ic.y][xn])
                    if ic.Time<= 9:
                        if ic.Time - cint(x*3) >= 2:
                            mods.Iris.draw_item(IceThornToDraw(xn, ic.y, 2, 7))
                        elif ic.Time - cint(x*3) == 1:
                            mods.Iris.draw_item(IceThornToDraw(xn, ic.y, 1, 7))
                        elif ic.Time - cint(x*3) == 0:
                            mods.Iris.draw_item(IceThornToDraw(xn, ic.y, 0, 7))
                        else:
                            pass
                    elif 9 <= ic.Time < 39:
                        mods.Iris.draw_item(IceThornToDraw(xn, ic.y, 2, 7))
                    
                    for en in entities:
                        if en.x == xn and en.y == ic.y:
                            en.frozen = True
            elif ic.direct == 'south':
                yn = ic.y
                for x in range(0, 3):
                    yn = ic.y + x
                    
                    if not 0 <= yn <= 14:
                        break
                    draw_block(ic.x, yn, Map[yn][ic.x])
                    if ic.Time<= 9:
                        if ic.Time - cint(x*3) >= 2:
                            mods.Iris.draw_item(IceThornToDraw(ic.x, yn, 2, 7))
                        elif ic.Time - cint(x*3) == 1:
                            mods.Iris.draw_item(IceThornToDraw(ic.x, yn, 1, 7))
                        elif ic.Time - cint(x*3) == 0:
                            mods.Iris.draw_item(IceThornToDraw(ic.x, yn, 0, 7))
                        else:
                            pass
                    elif 9 <= ic.Time < 39:
                        mods.Iris.draw_item(IceThornToDraw(ic.x, yn, 2, 7))
                    
                    for en in entities:
                        if en.x == ic.x and en.y == yn:
                            en.frozen = True
            elif ic.direct == 'north':
                yn = ic.y
                for x in range(0, 3):
                    yn = ic.y - x
                    if not 0 <= yn <= 14:
                        break
                    draw_block(ic.x, yn, Map[yn][ic.x])
                    if ic.Time<= 9:
                        if ic.Time - cint(x*3) >= 2:
                            mods.Iris.draw_item(IceThornToDraw(ic.x, yn, 2, 7))
                        elif ic.Time - cint(x*3) == 1:
                            mods.Iris.draw_item(IceThornToDraw(ic.x, yn, 1, 7))
                        elif ic.Time - cint(x*3) == 0:
                            mods.Iris.draw_item(IceThornToDraw(ic.x, yn, 0, 7))
                        else:
                            pass
                    elif 9 <= ic.Time < 39:
                        mods.Iris.draw_item(IceThornToDraw(ic.x, yn, 2, 7))
                    
                    for en in entities:
                        if en.x == ic.x and en.y == yn:
                            en.frozen = True
            
            ice_new.append(ic)
        else:
            pass
    icelist = ice_new

def cango(who, direct):
    if direct == 'east':
        if who.x + 1 < 20 and Map[who.y][who.x+1] == Void and not hasb(who.x+1, who.y):
            return True
        else:
            return False
    elif direct == 'south':
        if who.y + 1 < 15 and Map[who.y+1][who.x] == Void and not hasb(who.x, who.y + 1):
            return True
        else:
            return False
    elif direct == 'west':
        if who.x - 1 >= 0 and Map[who.y][who.x-1] == Void and not hasb(who.x - 1, who.y) :
            return True
        else:
            return False
    elif direct == 'north':
        if who.y - 1 >= 0 and Map[who.y-1][who.x] == Void and not hasb(who.x, who.y - 1):
            return True
        else:
            return False
    else:
        print_warning(f'Error direction: {direct}')

def unsafe(who, power_Now = 3):
    if hasb(x = who.x, y = who.y):
        return True
    xn, yn = who.x, who.y
    power = 0
    i = xn
    while i < 19:
        i += 1
        if Map[yn][i] != Void:
            break;
        power += 1
        if hasb(x = i, y = yn) and power_Now > power:
            return True
    
    power = 0
    i = xn
    while i > 0:
        i -= 1
        if Map[yn][i] != Void:
            break;
        power += 1
        if hasb(x = i, y = yn) and power_Now > power:
            return True
    
    power = 0
    i = yn
    while i < 14:
        i += 1
        if Map[i][xn] != Void:
            break;
        power += 1
        if hasb(x = xn, y = i) and power_Now > power:
            return True
    
    power = 0
    i = yn
    while i > 0:
        i -= 1
        if Map[i][xn] != Void:
            break;
        power += 1
        if hasb(x = xn, y = i) and power_Now > power:
            return True
    
    return False

def cango_safe(who, direct, power_Now = 3):
    if not cango(who, direct):
        return False
    xn, yn = 0, 0 # x, y new
    if direct == 'east':
        xn = who.x + 1
        yn = who.y
    elif direct == 'south':
        xn = who.x
        yn = who.y + 1
    elif direct == 'west':
        xn = who.x - 1
        yn = who.y
    elif direct == 'north':
        xn = who.x
        yn = who.y - 1
    power = 0
    i = xn
    while i < 19:
        i += 1
        if Map[yn][i] != Void:
            break;
        power += 1
        if hasb(x = i, y = yn) and power_Now > power:
            return False
    
    power = 0
    i = xn
    while i > 0:
        i -= 1
        if Map[yn][i] != Void:
            break;
        power += 1
        if hasb(x = i, y = yn) and power_Now > power:
            return False
    
    power = 0
    i = yn
    while i < 14:
        i += 1
        if Map[i][xn] != Void:
            break;
        power += 1
        if hasb(x = xn, y = i) and power_Now > power:
            return False
    
    power = 0
    i = yn
    while i > 0:
        i -= 1
        if Map[i][xn] != Void:
            break;
        power += 1
        if hasb(x = xn, y = i) and power_Now > power:
            return False
    
    return True

class Entity(object):
    
    def __init__(self):
        '''Entity base data, including Player and Enemy.'''
        #position
        self.x  = 0
        self.xp = 0  # 10 max, 1 or 2 add
        self.y  = 0
        self.yp = 0
        
        #properties
        self.power    = 1
        self.capacity = 0
        self.speed    = 2
        self.health   = 1
        self.ctype    = 'entity'
        self.team     = 0

class Player(Entity):
    
    def __init__(self):
        self.x = 16
        self.y = 11
        self.xp = 0
        self.yp = 0
        self.health = 1
        self.speed = mods.cfg.player_speed()
        self.ID = 0
        
        self.nextTps = 0
        self.rebirth = -1
        
        #self.bx = 0
        #self.by = 0
        self.using_b = False
        self.capacity = 1 if mods.cfg.DoCapacityIncrease else 3
        self.bbtime = 24
        
        self.kill = 0
        self.died = 0
        self.goal = 0
        self.ender_pearl_timeout = 0
        self.tnt_timeout = 0
        self.ice_timeout = 0
        self.facing = 'west'
        
        self.frozen = False
        self.slow   = -1
        self.shield = False
    
    def mov_effect(self):
        if self.frozen == True:
            self.frozen = False
            self.slow = ftps() + 15_000
            self.speed = cint(mods.cfg.player_speed() / 3)
        if self.slow >= 0:
            if ftps() >= self.slow:
                self.slow = -1
                self.speed = cint(mods.cfg.player_speed())
            else:
                pass

class Enemy(Entity):
    
    def __init__(self, ID):
        self.x = 3 if not mods.cfg.DoEnemyDisperse else 3 if ID in (1, 3) else 16
        self.y = 3 if not mods.cfg.DoEnemyDisperse else 3 if ID in (1, 2) else 11
        self.xp = 0
        self.yp = 0
        self.health = 1
        self.speed = mods.cfg.enemy_speed_1()
        self.ID = ID
        
        self.direct_last = 'east'
        self.nextTps = 0
        self.rebirth = -1
        
        #self.bx = 0
        #self.by = 0
        self.using_b = False
        self.capacity = 1 if mods.cfg.DoCapacityIncrease else 3
        self.bbtime = 24
        
        self.bedx = 3 if self.ID in (1, 3) else 16
        self.bedy = 3 if self.ID in (1, 2) else 11
        
        self.kill = 0
        self.died = 0
        self.goal = 0
        
        self.frozen = False
        self.slow   = -1
        self.shield = False
    
    def mov_effect(self):
        if self.frozen == True:
            self.frozen = False
            self.slow = ftps() + 15_000
            self.speed = cint(mods.cfg.enemy_speed_1() / 3)
        if self.slow >= 0:
            if ftps() >= self.slow:
                self.slow = -1
                self.speed = cint(mods.cfg.enemy_speed_1())
            else:
                pass
        
    def run(self, pl, power_max, e01, e02):
        global Map
        self.nextTps = ftps() + 50
        if self.health <= 0:
            if self.rebirth < 0:
                self.rebirth = 60 if self.shield == False else 1
                self.died += 1
            #if self.using_b == True:
            #    Map[self.by][self.bx] = Void
            if Map[3][3] != Bed and not self.shield:
                Ellipsis
            else:
                if self.rebirth < 0:
                    self.rebirth = 60
                    self.died += 1
                elif self.rebirth == 0:
                    self.health = 1
                    self.x = 3 if not mods.cfg.DoEnemyDisperse else self.bedx
                    self.y = 3 if not mods.cfg.DoEnemyDisperse else self.bedy
                    self.xp = 0
                    self.yp = 0
                    self.rebirth = -1
                    self.using_b = False
                    if not self.shield:
                        self.goal = 0
                        self.frozen = False
                        self.slow = -1
                        self.speed = mods.cfg.enemy_speed_1()
                    else:
                        self.shield = False
                else:
                    self.rebirth -= 1
            return
        
        if self.frozen == True:
            self.mov_effect()
            return
        else:
            self.mov_effect()
        
        #if self.xp != 0 or self.yp != 0:
        #    for x in range(max(pl.x-1, 0), min(pl.x+2, 20)):
        #        for y in range(max(pl.y-1, 0), min(pl.y+2, 15)):
        #            draw_block(x, y, Map[y][x])
        
        if self.x > 19:
            self.x = 19
            mods.CrystalLib.print_warning(f'enemy {self.ID} out of range (in Map direction x)')
        if self.y > 14:
            self.y = 14
            print_warning(f'enemy {self.ID} out of range (in Map direction y)')
        if self.xp > 0:
            self.xp += self.speed
            if self.xp > 60:
                self.xp = 0
                self.x += 1
        elif self.yp > 0:
            self.yp += self.speed
            if self.yp > 60:
                self.yp = 0
                self.y += 1
        elif self.xp < 0:
            self.xp -= self.speed
            if self.xp < -60:
                self.xp = 0
                self.x -= 1
        elif self.yp < 0:
            self.yp -= self.speed
            if self.yp < -60:
                self.yp = 0
                self.y -= 1
        else:
            if mods.cfg.FriendFire == True:
                if unsafe(self, power_max):
                    try_times = 12 # 立即移动
                    while try_times > 0:
                        try_times -= 1
                        if prob(25) and cango(self, 'east'):
                            self.xp = 1
                            self.direct_last = 'east'
                            try_times = -1
                        elif prob(25) and cango(self, 'north'):
                            self.yp = -1
                            self.direct_last = 'north'
                            try_times = -1
                        elif prob(25) and cango(self, 'west'):
                            self.xp = -1
                            self.direct_last = 'west'
                            try_times = -1
                        elif cango(self, 'south'):
                            self.yp = 1
                            self.direct_last = 'south'
                            try_times = -1
                    
                elif prob(50):
                    # continue last direct
                    if self.direct_last == 'east' and cango_safe(self, 'east', power_max):
                        self.xp = 1
                    elif self.direct_last == 'west' and cango_safe(self, 'west', power_max):
                        self.xp = -1
                    elif self.direct_last == 'north' and cango_safe(self, 'north', power_max):
                        self.yp = -1
                    elif cango_safe(self, 'south', power_max):
                        self.yp = 1
                elif prob(35):
                    # try to find player
                    if self.x - pl.x > 1 and cango_safe(self, 'west', power_max):
                        self.xp = -1
                    elif pl.x - self.x > 1 and cango_safe(self, 'east', power_max):
                        self.xp = 1
                    elif self.y - pl.y > 1 and cango_safe(self, 'north', power_max):
                        self.yp = -1
                    elif pl.y - self.y > 1 and cango_safe(self, 'south', power_max):
                        self.yp = 1
                    else:
                        if prob(25) and cango_safe(self, 'east', power_max):
                            self.xp = 1
                            self.direct_last = 'east'
                        elif prob(25) and cango_safe(self, 'north', power_max):
                            self.yp = -1
                            self.direct_last = 'north'
                        elif prob(25) and cango_safe(self, 'west', power_max):
                            self.xp = -1
                            self.direct_last = 'west'
                        elif cango_safe(self, 'south', power_max):
                            self.yp = 1
                            self.direct_last = 'south'
                else:
                    if prob(25) and cango_safe(self, 'east', power_max):
                        self.xp = 1
                        self.direct_last = 'east'
                    elif prob(25) and cango_safe(self, 'north', power_max):
                        self.yp = -1
                        self.direct_last = 'north'
                    elif prob(25) and cango_safe(self, 'west', power_max):
                        self.xp = -1
                        self.direct_last = 'west'
                    elif cango_safe(self, 'south', power_max):
                        self.yp = 1
                        self.direct_last = 'south'
        
            else:
                # No FriendFire
                if prob(50):
                    # continue last direct
                    if self.direct_last == 'east' and cango(self, 'east'):
                        self.xp = 1
                    elif self.direct_last == 'west' and cango(self, 'west'):
                        self.xp = -1
                    elif self.direct_last == 'north' and cango(self, 'north'):
                        self.yp = -1
                    elif cango(self, 'south'):
                        self.yp = 1
                elif prob(35):
                    # try to find player
                    if self.x - pl.x > 1 and cango(self, 'west'):
                        self.xp = -1
                    elif pl.x - self.x > 1 and cango(self, 'east'):
                        self.xp = 1
                    elif self.y - pl.y > 1 and cango(self, 'north'):
                        self.yp = -1
                    elif pl.y - self.y > 1 and cango(self, 'south'):
                        self.yp = 1
                    else:
                        if prob(25) and cango(self, 'east'):
                            self.xp = 1
                            self.direct_last = 'east'
                        elif prob(25) and cango(self, 'north'):
                            self.yp = -1
                            self.direct_last = 'north'
                        elif prob(25) and cango(self, 'west'):
                            self.xp = -1
                            self.direct_last = 'west'
                        elif cango(self, 'south'):
                            self.yp = 1
                            self.direct_last = 'south'
                else:
                    if prob(25) and cango(self, 'east'):
                        self.xp = 1
                        self.direct_last = 'east'
                    elif prob(25) and cango(self, 'north'):
                        self.yp = -1
                        self.direct_last = 'north'
                    elif prob(25) and cango(self, 'west'):
                        self.xp = -1
                        self.direct_last = 'west'
                    elif cango(self, 'south'):
                        self.yp = 1
                        self.direct_last = 'south'
        
        if self.goal >= 3:
            # TNT
            if abs(pl.y - self.y) < 5:
                if 0 < pl.x - self.x <= 5: # east
                    TNTList.append(TNT(x = min(self.x + mods.cfg.TNTPower, 19), y = self.y, belong = self.ID,Time=ftps()+1_600))
                    self.goal -= 3
                elif 0 < self.x - pl.x <= 5: # west
                    TNTList.append(TNT(x = max(self.x - mods.cfg.TNTPower, 0), y = self.y, belong = self.ID,Time=ftps()+1_600))
                    self.goal -= 3
            elif abs(pl.x - self.x) < 5:
                if 0 < pl.y - self.y <= 5: # south
                    TNTList.append(TNT(y = min(self.y + mods.cfg.TNTPower, 14), x = self.x, belong = self.ID,Time=ftps()+1_600))
                    self.goal -= 3
                elif 0 < self.y - pl.y <= 5: # north
                    TNTList.append(TNT(y = max(self.y - mods.cfg.TNTPower, 0), x = self.x, belong = self.ID,Time=ftps()+1_600))
                    self.goal -= 3
                
        if self.goal >= 2 and (9<=self.x<=12) and (10 <= self.y <= 12):
            self.goal -= 2
            self.x += mods.cfg.item_ender_pearl_distance()
            if self.x > 19:
                self.x = 19
        if self.goal >= 2 and 4<=self.y<=8 and (15 <= self.x <= 17):
            self.goal -= 2
            self.y += mods.cfg.item_ender_pearl_distance()
            if self.y > 14:
                self.y = 14
        if Map[self.y][self.x] == Void and mods.EntityLib.setblock_case(self.x, self.y):
            Map[self.y][self.x] = Soft
        
        if self.capacity > 0:
            setbomb_prob = 16 if EulaDis(self.x, self.y, pl.x, pl.y) <= power_max else 5
            if prob(setbomb_prob) and not hasb(self.x, self.y) and Map[self.y][self.x] == Void:
                blist.append(Bomb(x = self.x, y = self.y, belong = self.ID, power = power_max, Time = ftps() + 2_200,
                                  color = mods.cfg.ask_e_color(self.ID)))
                self.capacity -= 1
        """
        if self.using_b == False:
            if prob(20) and Map[self.y][self.x] == Void:
                Map[self.y][self.x] = BB
                self.using_b = True
                self.bbtime = 24
                self.bx = self.x
                self.by = self.y
        else:
            if self.bbtime > 0:
                self.bbtime -= 1
                #pygame.draw.circle(screen, (255, 0, 0), (pl.bx, pl.by), 20)
            else:
                #BOMBBBBBBBB!
                for bp in range(1, power_max):
                    if self.bx + bp > 19:
                        break
                    if pl.x == self.bx+bp and pl.y == self.by and pl.health > 0:
                        pl.health = 0
                        self.kill += 1
                        self.goal += 1
                    if mods.cfg.FriendFire == True:
                        if self.x == self.bx+bp and self.y == self.by and self.health > 0:
                            self.health = 0
                            #self.died += 1
                        if e01.x == self.bx+bp and e01.y == self.by and e01.health > 0:
                            e01.health = 0
                            #e01.died += 1
                        if e02.x == self.bx+bp and e02.y == self.by and e02.health > 0:
                            e02.health = 0
                            #e02.died += 1
                    
                    
                    if Map[self.by][self.bx + bp] == Soft:
                        Map[self.by][self.bx + bp] = Void
                        break
                    elif Map[self.by][self.bx + bp] == Hard:
                        break
                    elif Map[self.by][self.bx + bp] == Bed:
                        if self.by > 8:
                            Map[self.by][self.bx + bp] = Void
                            printm(f'Enemy {self.ID} destroied your bed!')
                        break
                    elif Map[self.by][self.bx + bp] == BB:
                        break
                for bp in range(1, power_max):
                    if self.bx - bp < 0:
                        break
                    if pl.x == self.bx-bp and pl.y == self.by and pl.health > 0:
                        pl.health = 0
                        self.kill += 1
                        self.goal += 1
                    if mods.cfg.FriendFire == True:
                        if self.x == self.bx-bp and self.y == self.by and self.health > 0:
                            self.health = 0
                            #self.died += 1
                        if e01.x == self.bx-bp and e01.y == self.by and e01.health > 0:
                            e01.health = 0
                            #e01.died += 1
                        if e02.x == self.bx-bp and e02.y == self.by and e02.health > 0:
                            e02.health = 0
                            #e02.died += 1
                    
                    
                    #if e2.x == pl.bx-bp and e2.y == pl.by:
                    #    e2.health = 0
                    #if e3.x == pl.bx-bp and e3.y == pl.by:
                    #    e3.health = 0
                    if Map[self.by][self.bx - bp] == Soft:
                        Map[self.by][self.bx - bp] = Void
                        break
                    elif Map[self.by][self.bx - bp] == Hard:
                        break
                    elif Map[self.by][self.bx - bp] == Bed:
                        if self.by > 8:
                            Map[self.by][self.bx - bp] = Void
                            printm(f'Enemy {self.ID} destroied your bed!')
                        break
                    elif Map[self.by][self.bx - bp] == BB:
                        break
                for bp in range(1, power_max):
                    if self.by + bp > 14:
                        break
                    if pl.y == self.by+bp and pl.x == self.bx and pl.health > 0:
                        pl.health = 0
                        self.kill += 1
                        self.goal += 1
                    if mods.cfg.FriendFire == True:
                        if self.y == self.by+bp and self.x == self.bx and self.health > 0:
                            self.health = 0
                            #self.died += 1
                        if e01.y == self.by+bp and e01.x == self.bx and e01.health > 0:
                            e01.health = 0
                            #e01.died += 1
                        if e02.y == self.by+bp and e02.x == self.bx and e02.health > 0:
                            e02.health = 0
                            #e02.died += 1
                    
                    
                    #if e2.y == pl.by+bp and e2.x == pl.bx:
                    #    e2.health = 0
                    #if e3.y == pl.by+bp and e3.x == pl.bx:
                    #    e3.health = 0
                    if Map[self.by + bp][self.bx] == Soft:
                        Map[self.by + bp][self.bx ] = Void
                        break
                    elif Map[self.by + bp][self.bx ] == Hard:
                        break
                    elif Map[self.by + bp][self.bx ] == Bed:
                        if self.bx > 8:
                            Map[self.by + bp][self.bx ] = Void
                            printm(f'Enemy {self.ID} destroied your bed!')
                        break
                    elif Map[self.by + bp][self.bx ] == BB:
                        break
                for bp in range(1, power_max):
                    if self.bx - bp < 0:
                        break
                    if pl.y == self.by-bp and pl.x == self.bx and pl.health > 0:
                        pl.health = 0
                        self.kill += 1
                        self.goal += 1
                    if mods.cfg.FriendFire == True:
                        if self.y == self.by-bp and self.x == self.bx and self.health > 0:
                            self.health = 0
                            #self.died += 1
                        if e01.y == self.by-bp and e01.x == self.bx and e01.health > 0:
                            e01.health = 0
                            #e01.died += 1
                        if e02.y == self.by-bp and e02.x == self.bx and e02.health > 0:
                            e02.health = 0
                            #e02.died += 1
                    
                    
                    #if e2.y == pl.by-bp and e2.x == pl.bx:
                    #    e2.health = 0
                    #if e3.y == pl.by-bp and e3.x == pl.bx:
                    #    e3.health = 0
                    if Map[self.by - bp][self.bx] == Soft:
                        Map[self.by - bp][self.bx ] = Void
                        break
                    elif Map[self.by - bp][self.bx ] == Hard:
                        break
                    elif Map[self.by - bp][self.bx ] == Bed:
                        if self.bx > 8:
                            Map[self.by - bp][self.bx ] = Void
                            printm(f'Enemy {self.ID} destroied your bed!')
                        break
                    elif Map[self.by - bp][self.bx ] == BB:
                        break
                Map[self.by][self.bx] = Void
                for x in range(max(self.bx-power_max+1, 0), min(self.bx+power_max, 20)):
                    for y in range(max(self.by-power_max+1, 0), min(self.by+power_max, 15)):
                        draw_block(x, y, Map[y][x])
                self.using_b = False
        """
        # above is olds.



class ExitGame(Exception):
        def __init__(self, value):
            self.value = value

        def __str__(self):
            return repr(self.value)

def Redraw():
    for x in range(0, 20):
        for y in range(0, 15):
            draw_block(x, y, Map[y][x])

first_run = True
def bedwar():
    global screen, Map, first_run, blist, TNTList, icelist
    mods.Iris.on_NewGame()
    blist = []
    TNTList = []
    icelist = []
    if not mods.cfg.SimplifyOutputInformation:
        printm('修改重生点信息。')
    Map[3][3] = Bed
    Map[11][16] = Bed
    for x in range(15, 18):
        for y in range(2, 5):
            Map[y][x] = Void
    for x in range(2, 5):
        for y in range(10, 13):
            Map[y][x] = Void
    for row in range(15):
        for col in range(20):
            draw_block(col, row, Map[row][col])
    if not mods.cfg.SimplifyOutputInformation:
        printm('显示地图完毕。')
    e1, e2, e3, pl = Enemy(1), Enemy(2), Enemy(3), Player()
    if not mods.cfg.SimplifyOutputInformation:
        printm('实体信息加载完毕。')
    #enemy_lived = 3
    power_max = 2 if mods.cfg.PowerIncrease == True else 3
    power_time = ftps() + 120_000
    Score_time = ftps() + 20_000
    Capac_time = ftps() + 65_000
    Shield_time= ftps() + 36_000
    
    Title_Bar = [None, 0] # 显示在屏幕中心的文字。用于提示事件。格式: [what:Union[None, str], tps_add:int]
    Player_bed_has_been_destroyed = False
    
    cpu_per = psutil.cpu_percent()
    mem_per = psutil.virtual_memory().percent
    cpu_mem_TPS = ftps() + 1000
    
    MovBombTPS = ftps()
    MovTNT_TPS = ftps()
    MovIceThornTps = ftps() + 50
    FPS_Tick = ftps() + 10
    #first_run = True
    fps_get_now = 0
    Time_Start = ftps()
    while True:
        fps.tick(mods.cfg.FPS_limit)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                raise ExitGame('Click quit button.')
        
        if Map[11][16] != Bed and Player_bed_has_been_destroyed == False:
            Title_Bar[0] = '重生点已被摧毁'
            Title_Bar[1] = ftps() + 3_800
            Player_bed_has_been_destroyed = True
        if Map[3][3] != Bed and e1.health<=0 and e2.health<=0 and e3.health <=0 and not e1.shield and not e2.shield and not e3.shield:
            printm('Player win.')
            Time_Used = ftps() - Time_Start
            textWin = f.render(f'You Win! Use time: {Time_Used/1000:5.1f}', True, (255, 80, 80))
            screen.blit(textWin, (1220, 600))
            pygame.display.flip()
            #pygame.time.wait(5_000)
            raise ExitGame('Game finish.')
        if Map[11][16] != Bed and pl.health <= 0 and not pl.shield:
            printm('Player lose.')
            Time_Used = ftps() - Time_Start
            textLose = f.render(f'You lose. Use time: {Time_Used/1000:5.1f}', True, (80, 80, 255))
            screen.blit(textLose, (1220, 600))
            pygame.display.flip()
            raise ExitGame('Game over.')
        if ftps() >= power_time:
            power_time = ftps() + 60_000
            if mods.cfg.PowerIncrease == True:
                power_max += 1
                if not mods.cfg.SimplifyOutputInformation:
                    printm('增加炸弹威力。')
                Title_Bar[0] = '增加炸弹威力'
                Title_Bar[1] = ftps() + 3_800
        if ftps() >= Score_time:
            Score_time = ftps() + 15_000
            if mods.cfg.DoGoalIncrease == True:
                pl.goal += 1
                e1.goal += 1
                e2.goal += 1
                e3.goal += 1
                if not mods.cfg.SimplifyOutputInformation:
                    printm('增加分数')
                Title_Bar[0] = '增加分数'
                Title_Bar[1] = ftps() + 3_800
        if ftps() >= Capac_time:
            Capac_time = ftps() + 37_000
            if mods.cfg.DoCapacityIncrease == True:
                pl.capacity += 1
                e1.capacity += 1
                e2.capacity += 1
                e3.capacity += 1
                if not mods.cfg.SimplifyOutputInformation:
                    printm('增加炸弹容量。')
                Title_Bar[0] = '增加炸弹容量'
                Title_Bar[1] = ftps() + 3_800
        if ftps() >= Shield_time:
            Shield_time = ftps() + 38_000
            if mods.cfg.DoEquipmentShield == True:
                if pl.health > 0:
                    pl.shield = True
                if e1.health > 0:
                    e1.shield = True
                if e2.health > 0:
                    e2.shield = True
                if e3.health > 0:
                    e3.shield = True
                if not mods.cfg.SimplifyOutputInformation:
                    printm('自动装备护盾')
                Title_Bar[0] = '自动装备护盾'
                Title_Bar[1] = ftps() + 3_800
        
        if ftps() >= cpu_mem_TPS:
            cpu_per = psutil.cpu_percent()
            mem_per = psutil.virtual_memory().percent
            cpu_mem_TPS = ftps() + 1_000
        
        fps_get_now = fps.get_fps()
        if ftps() >= FPS_Tick:
            pygame.draw.rect(screen, (0,0,0), (1201, 0, 298, 900))
            if mods.cfg.SimplifyDebuggingInformation == True:
                Text1 = f.render(f'FPS: {fps_get_now:3.2f} limit:{"垂直同步" if mods.cfg.FPS_limit == 60 else mods.cfg.FPS_limit if mods.cfg.FPS_limit <= 1000 else "无限制"} power: {power_max}', True, (255, 0 ,0))
                screen.blit(Text1, (1220, 20))
                Text_player = f.render(f'({pl.goal})Player: ({pl.x},{pl.y}) {"live" if pl.health>0 else "died"} kill: {pl.kill} died: {pl.died}', True, (0,255,0))
                screen.blit(Text_player, (1201, 50))
                Text_e1 = f.render(f'({e1.goal})Enemy1: ({e1.x},{e1.y}) {"live" if e1.health>0 else "died"} kill: {e1.kill} died: {e1.died}', True, (0, 255, 0))
                screen.blit(Text_e1, (1201, 80))
                Text_e2 = f.render(f'({e2.goal})Enemy2: ({e2.x},{e2.y}) {"live" if e2.health>0 else "died"} kill: {e2.kill} died: {e2.died}', True, (0, 255, 0))
                screen.blit(Text_e2, (1201, 110))
                Text_e3 = f.render(f'({e3.goal})Enemy3: ({e3.x},{e3.y}) {"live" if e3.health>0 else "died"} kill: {e3.kill} died: {e3.died}', True, (0, 255, 0))
                screen.blit(Text_e3, (1201, 140))
            else:
                mods.printlib.OutTextxy(f'FPS: {fps_get_now:3.2f} limit:{"垂直同步" if mods.cfg.EnableVerticalSynchronization == True else mods.cfg.FPS_limit if mods.cfg.FPS_limit <= 1000 else "无限制"} power: {power_max}', (255,0,0), ('right', 0))
                mods.printlib.OutTextxy(f'Player:  Position: ({pl.x},{pl.y})  {"live" if pl.health>0 else "died"}', (0, 255, 255), ('right', 1))
                mods.printlib.OutTextxy(f'    Goal:{pl.goal} Kill:{pl.kill} Death:{pl.died}', (0,255,255), ('right', 2))
                mods.printlib.OutTextxy(f'    Capacity:{pl.capacity} Rebirth:{cint(pl.rebirth/100)}', (0,255,255), ('right', 3))
                mods.printlib.OutTextxy(f'Enemy1:  Position: ({e1.x},{e1.y})  {"live" if e1.health>0 else "died"}', mods.cfg.color_e1, ('right', 4))
                mods.printlib.OutTextxy(f'    Goal:{e1.goal} Kill:{e1.kill} Death:{e1.died}', mods.cfg.color_e1, ('right', 5))
                mods.printlib.OutTextxy(f'    Capacity:{e1.capacity} Rebirth:{cint(e1.rebirth/20)}', mods.cfg.color_e1, ('right', 6))
                mods.printlib.OutTextxy(f'Enemy2:  Position: ({e2.x},{e2.y})  {"live" if e2.health>0 else "died"}', mods.cfg.color_e2, ('right', 7))
                mods.printlib.OutTextxy(f'    Goal:{e2.goal} Kill:{e2.kill} Death:{e2.died}', mods.cfg.color_e2, ('right', 8))
                mods.printlib.OutTextxy(f'    Capacity:{e2.capacity} Rebirth:{cint(e2.rebirth/20)}', mods.cfg.color_e2, ('right', 9))
                mods.printlib.OutTextxy(f'Enemy3:  Position: ({e3.x},{e3.y})  {"live" if e3.health>0 else "died"}', mods.cfg.color_e3, ('right', 10))
                mods.printlib.OutTextxy(f'    Goal:{e3.goal} Kill:{e3.kill} Death:{e3.died}', mods.cfg.color_e3, ('right', 11))
                mods.printlib.OutTextxy(f'    Capacity:{e3.capacity} Rebirth:{cint(e3.rebirth/20)}', mods.cfg.color_e3, ('right', 12))
                
                # 状态指示器
                if pl.shield:
                    mods.Iris.draw_image('effect_shield', (1469, 2 * 30 + 10))
                if pl.slow >= 0:
                    mods.Iris.draw_image('effect_slow', (1469, 3 * 30 + 10))
                if e1.shield:
                    mods.Iris.draw_image('effect_shield', (1469, 5 * 30 + 10))
                if e1.slow >= 0:
                    mods.Iris.draw_image('effect_slow', (1469, 6 * 30 + 10))
                if e2.shield:
                    mods.Iris.draw_image('effect_shield', (1469, 8 * 30 + 10))
                if e2.slow >= 0:
                    mods.Iris.draw_image('effect_slow', (1469, 9 * 30 + 10))
                if e3.shield:
                    mods.Iris.draw_image('effect_shield', (1469, 11 * 30 + 10))
                if e3.slow >= 0:
                    mods.Iris.draw_image('effect_slow', (1469, 12 * 30 + 10))
                
                
                """
                if mods.cfg.PowerIncrease and mods.cfg.DoGoalIncrease:
                    if power_time < Score_time:
                        mods.printlib.OutTextxy(f'下一事件: 增加炸弹威力    倒计时: {cint((power_time - ftps()) / 1000)} s', (255, 255, 0), ('right', 14))
                    else:
                        mods.printlib.OutTextxy(f'下一事件: 增加分数    倒计时: {cint((Score_time - ftps()) / 1000)} s', (255, 255, 0), ('right', 14))
                else:
                    if mods.cfg.PowerIncrease:
                        mods.printlib.OutTextxy(f'下一事件: 增加炸弹威力    倒计时: {cint((power_time - ftps()) / 1000)} s', (255, 255, 0), ('right', 14))
                    else:
                        if mods.cfg.DoGoalIncrease:
                            mods.printlib.OutTextxy(f'下一事件: 增加分数    倒计时: {cint((Score_time - ftps()) / 1000)} s', (255, 255, 0), ('right', 14))
                """
                if not mods.cfg.PowerIncrease and not mods.cfg.DoGoalIncrease and not mods.cfg.DoCapacityIncrease and not mods.cfg.DoEquipmentShield:
                    Ellipsis
                else:
                    pot, dgt, dct, sht = power_time, Score_time, Capac_time, Shield_time
                    if not mods.cfg.PowerIncrease:
                        pot = 922_114_514_1919810_0
                    if not mods.cfg.DoGoalIncrease:
                        dgt = 922_114_514_1919810_0
                    if not mods.cfg.DoCapacityIncrease:
                        dct = 922_114_514_1919810_0
                    if not mods.cfg.DoEquipmentShield:
                        sht = 922_114_514_1919810_0
                    time_min = min(pot, dgt, dct, sht)
                    if pot == time_min:
                        mods.printlib.OutTextxy(f'下一事件: 增加炸弹威力    倒计时: {cint((power_time - ftps()) / 1000)} s', (255, 255, 0), ('right', 14))
                    elif dgt == time_min:
                        mods.printlib.OutTextxy(f'下一事件: 增加分数    倒计时: {cint((Score_time - ftps()) / 1000)} s', (255, 255, 0), ('right', 14))
                    elif sht == time_min:
                        mods.printlib.OutTextxy(f'下一事件: 装备护盾    倒计时: {cint((Shield_time - ftps()) / 1000)} s', (255, 255, 0), ('right', 14))
                    else:
                        mods.printlib.OutTextxy(f'下一事件: 增加炸弹容量    倒计时: {cint((Capac_time - ftps()) / 1000)} s', (255, 255, 0), ('right', 14))
                mods.printlib.xyprint(f'Facing: {pl.facing}', (255, 255, 255), ('right', 12))
                
                mods.printlib.xyprint(f'CPU: {cpu_per}  Memory: {mem_per}', (0, 255, 0), ('right', 17))
            
            FPS_Tick = ftps() + 100
        
        if first_run == True and not mods.cfg.SimplifyOutputInformation:
            printm('01 judge finished.')
        
        kp = pygame.key.get_pressed()
        if first_run == True and not mods.cfg.SimplifyOutputInformation:
            printm('获取按键信息。')
        if kp[pygame.K_p]:
            mods.CrystalLib.Pause()
            Redraw()
        
        if ftps() > MovBombTPS:
            MovBombTPS = ftps() + 50
            MovBomb(pl, e1, e2, e3, isOnlyRender = False)
        if ftps() > MovTNT_TPS:
            MovTNT(pl, e1, e2, e3)
            MovTNT_TPS = ftps() + 50
        
        #if (pl.xp != 0 or pl.yp != 0) and ((pl.nextTps - ftps()) % 4 == 0):
        #    for x in range(max(pl.x-1, 0), min(pl.x+2, 20)):
        #        for y in range(max(pl.y-1, 0), min(pl.y+2, 15)):
        #            draw_block(x, y, Map[y][x])
        
        if ftps()>= pl.nextTps:
            if pl.health <= 0:
                if pl.rebirth < 0:
                    pl.rebirth = 480 if pl.shield == False else 1
                    pl.died += 1
                    #pl.goal = 0
                elif pl.rebirth == 0:
                    pl.x = 16
                    pl.y = 11
                    pl.health = 1
                    pl.rebirth = -1
                    pl.xp = 0
                    pl.yp = 0
                    pl.using_b = False
                    if not pl.shield:
                        pl.goal = 0
                        pl.frozen = False
                        pl.slow = -1
                        pl.speed = mods.cfg.player_speed()
                    else:
                        pl.shield = False
                else:
                    pl.rebirth -= 1
            
            if pl.xp > 0:
                pl.xp += pl.speed
                if pl.xp > 60:
                    pl.xp = 0
                    pl.x += 1
            elif pl.yp > 0:
                pl.yp += pl.speed
                if pl.yp > 60:
                    pl.yp = 0
                    pl.y += 1
            elif pl.xp < 0:
                pl.xp -= pl.speed
                if pl.xp < -60:
                    pl.xp = 0
                    pl.x -= 1
            elif pl.yp < 0:
                pl.yp -= pl.speed
                if pl.yp < -60:
                    pl.yp = 0
                    pl.y -= 1
            else:
                if kp[pygame.K_UP] and cango(pl, 'north') and pl.health > 0 and not pl.frozen:
                    pl.yp = -1
                elif kp[pygame.K_DOWN] and cango(pl, 'south') and pl.health > 0 and not pl.frozen:
                    pl.yp = 1
                elif kp[pygame.K_LEFT] and cango(pl, 'west') and pl.health > 0 and not pl.frozen:
                    pl.xp = -1
                elif kp[pygame.K_RIGHT] and cango(pl, 'east') and pl.health > 0 and not pl.frozen:
                    pl.xp = 1
            if pl.health > 0 and not pl.frozen:
                if kp[pygame.K_UP]:
                    pl.facing = 'north'
                elif kp[pygame.K_DOWN]:
                    pl.facing = 'south'
                elif kp[pygame.K_LEFT]:
                    pl.facing = 'west'
                elif kp[pygame.K_RIGHT]:
                    pl.facing = 'east'
            
            if pl.ender_pearl_timeout > 0:
                pl.ender_pearl_timeout -= 1
            if kp[pygame.K_w] and pl.ender_pearl_timeout <= 0 and pl.goal>=2 and pl.health > 0:
                pl.ender_pearl_timeout = 200
                pl.y -= mods.cfg.item_ender_pearl_distance()
                if pl.y < 0:
                    pl.y = 0
                pl.goal -= 2
            if kp[pygame.K_a] and pl.ender_pearl_timeout <= 0 and pl.goal>=2 and pl.health > 0:
                pl.ender_pearl_timeout = 200
                pl.x -= mods.cfg.item_ender_pearl_distance()
                if pl.x < 0:
                    pl.x = 0
                pl.goal -= 2
            if kp[pygame.K_s] and pl.ender_pearl_timeout <= 0 and pl.goal>=2 and pl.health > 0:
                pl.ender_pearl_timeout = 200
                pl.y += mods.cfg.item_ender_pearl_distance()
                if pl.y > 14:
                    pl.y = 14
                pl.goal -= 2
            if kp[pygame.K_d] and pl.ender_pearl_timeout <= 0 and pl.goal>=2 and pl.health > 0:
                pl.ender_pearl_timeout = 200
                pl.x += mods.cfg.item_ender_pearl_distance()
                if pl.x > 19:
                    pl.x = 19
                pl.goal -= 2
            
            if pl.tnt_timeout > 0:
                pl.tnt_timeout -= 1
            if kp[pygame.K_t] and pl.tnt_timeout <= 0 and pl.goal >= 3 and pl.health > 0 and not pl.frozen:
                pl.tnt_timeout = 60
                if pl.facing == 'west':
                    TNTList.append(TNT(y = pl.y, x = max(0, pl.x - mods.cfg.TNTPower), belong = 0,Time=ftps()+1_600))
                    pl.goal -= 3
                elif pl.facing == 'east':
                    TNTList.append(TNT(y = pl.y, x = min(19, pl.x + mods.cfg.TNTPower), belong = 0,Time=ftps()+1_600))
                    pl.goal -= 3
                elif pl.facing == 'south':
                    TNTList.append(TNT(x = pl.x, y = min(14, pl.y + mods.cfg.TNTPower), belong = 0,Time=ftps()+1_600))
                    pl.goal -= 3
                else:
                    TNTList.append(TNT(x = pl.x, y = max(0, pl.y - mods.cfg.TNTPower), belong = 0,Time=ftps()+1_600))
                    pl.goal -= 3
            
            if pl.ice_timeout > 0:
                pl.ice_timeout -= 1
            if kp[pygame.K_i] and pl.ice_timeout <= 0 and pl.goal >= 1 and pl.health > 0 and not pl.frozen:
                pl.ice_timeout = 70
                xn, yn = pl.x, pl.y
                if pl.facing == 'east':
                    xn += 1
                elif pl.facing == 'south':
                    yn += 1
                elif pl.facing == 'west':
                    xn -= 1
                else:
                    yn -= 1
                if 0 <= xn <= 19 and 0 <= yn <= 14:
                    icelist.append(IceThorn(x = xn, y = yn, direct = pl.facing, Time = 0))
            
            """
            if kp[pygame.K_SPACE] and pl.using_b == False and Map[pl.y][pl.x] == Void and pl.health > 0:
                Map[pl.y][pl.x] = BB
                pl.using_b = True
                pl.bbtime = 160
                pl.bx = pl.x
                pl.by = pl.y
            """
            if kp[pygame.K_SPACE] and pl.capacity > 0 and not hasb(pl.x, pl.y) and pl.health > 0 and Map[pl.y][pl.x] == Void and not pl.frozen:
                blist.append(Bomb(x = pl.x, y = pl.y, Time = ftps() + 2_200, belong = 0, color = (50, 255, 255), power = power_max))
                pl.capacity -= 1
            if kp[pygame.K_b] and Map[pl.y][pl.x] == Void and pl.health > 0 and not pl.frozen:
                Map[pl.y][pl.x] = Soft
            
            """
            if pl.using_b == True:
                if pl.bbtime > 0:
                    pl.bbtime -= 1
                    pygame.draw.circle(screen, (255, 0, 0), (pl.bx, pl.by), 20)
                else:
                    #BOMBBBBBBBB!
                    for bp in range(1, power_max):
                        if pl.bx + bp > 19:
                            break
                        if e1.x == pl.bx+bp and e1.y == pl.by and e1.health > 0:
                            e1.health = 0
                            pl.kill += 1
                            pl.goal += 1
                        if e2.x == pl.bx+bp and e2.y == pl.by and e2.health > 0:
                            e2.health = 0
                            pl.kill += 1
                            pl.goal += 1
                        if e3.x == pl.bx+bp and e3.y == pl.by and e3.health > 0:
                            e3.health = 0
                            pl.kill += 1
                            pl.goal += 1
                        if mods.cfg.FriendFire == True and pl.x == pl.bx+bp and pl.y == pl.by and pl.health > 0:
                            pl.health = 0
                            #pl.died += 1
                        
                        if Map[pl.by][pl.bx + bp] == Soft:
                            Map[pl.by][pl.bx + bp] = Void
                            break
                        elif Map[pl.by][pl.bx + bp] == Hard:
                            break
                        elif Map[pl.by][pl.bx + bp] == Bed:
                            if pl.by < 10:
                                Map[pl.by][pl.bx + bp] = Void
                            break
                        elif Map[pl.by][pl.bx + bp] == BB:
                            break
                    for bp in range(1, power_max):
                        if pl.bx - bp < 0:
                            break
                        if e1.x == pl.bx-bp and e1.y == pl.by and e1.health > 0:
                            e1.health = 0
                            pl.kill += 1
                            pl.goal += 1
                        if e2.x == pl.bx-bp and e2.y == pl.by and e2.health > 0:
                            e2.health = 0
                            pl.kill += 1
                            pl.goal += 1
                        if e3.x == pl.bx-bp and e3.y == pl.by and e3.health > 0:
                            e3.health = 0
                            pl.kill += 1
                            pl.goal += 1
                        if mods.cfg.FriendFire == True and pl.x == pl.bx-bp and pl.y == pl.by and pl.health > 0:
                            pl.health = 0
                            #pl.died += 1
                        
                        if Map[pl.by][pl.bx - bp] == Soft:
                            Map[pl.by][pl.bx - bp] = Void
                            break
                        elif Map[pl.by][pl.bx - bp] == Hard:
                            break
                        elif Map[pl.by][pl.bx - bp] == Bed:
                            if pl.by < 10:
                                Map[pl.by][pl.bx - bp] = Void
                            break
                        elif Map[pl.by][pl.bx - bp] == BB:
                            break
                    for bp in range(1, power_max):
                        if pl.by + bp > 14:
                            break
                        if e1.y == pl.by+bp and e1.x == pl.bx and e1.health > 0:
                            e1.health = 0
                            pl.kill += 1
                            pl.goal += 1
                        if e2.y == pl.by+bp and e2.x == pl.bx and e2.health > 0:
                            e2.health = 0
                            pl.kill += 1
                            pl.goal += 1
                        if e3.y == pl.by+bp and e3.x == pl.bx and e3.health > 0:
                            e3.health = 0
                            pl.kill += 1
                            pl.goal += 1
                        if mods.cfg.FriendFire == True and pl.y == pl.by+bp and pl.x == pl.bx and pl.health > 0:
                            pl.health = 0
                            #pl.died += 1
                        
                        if Map[pl.by + bp][pl.bx] == Soft:
                            Map[pl.by + bp][pl.bx ] = Void
                            break
                        elif Map[pl.by + bp][pl.bx ] == Hard:
                            break
                        elif Map[pl.by + bp][pl.bx ] == Bed:
                            if pl.bx < 10:
                                Map[pl.by + bp][pl.bx ] = Void
                            break
                        elif Map[pl.by + bp][pl.bx ] == BB:
                            break
                    for bp in range(1, power_max):
                        if pl.by - bp < 0:
                            break
                        if e1.y == pl.by-bp and e1.x == pl.bx and e1.health > 0:
                            e1.health = 0
                            pl.kill += 1
                            pl.goal += 1
                        if e2.y == pl.by-bp and e2.x == pl.bx and e2.health > 0:
                            e2.health = 0
                            pl.kill += 1
                            pl.goal += 1
                        if e3.y == pl.by-bp and e3.x == pl.bx and e3.health > 0:
                            e3.health = 0
                            pl.kill += 1
                            pl.goal += 1
                        if mods.cfg.FriendFire == True and pl.y == pl.by-bp and pl.x == pl.bx and pl.health > 0:
                            pl.health = 0
                            #pl.died += 1
                        
                        if Map[pl.by - bp][pl.bx] == Soft:
                            Map[pl.by - bp][pl.bx ] = Void
                            break
                        elif Map[pl.by - bp][pl.bx ] == Hard:
                            break
                        elif Map[pl.by - bp][pl.bx ] == Bed:
                            if pl.bx < 10:
                                Map[pl.by - bp][pl.bx ] = Void
                            break
                        elif Map[pl.by - bp][pl.bx ] == BB:
                            break
                    Map[pl.by][pl.bx] = Void
                    for x in range(max(pl.bx-power_max+1, 0), min(pl.bx+power_max, 20)):
                        for y in range(max(pl.by-power_max+1, 0), min(pl.by+power_max, 15)):
                            draw_block(x, y, Map[y][x])
                    pl.using_b = False
            """
            
            pl.nextTps = ftps() + 10
        if first_run and not mods.cfg.SimplifyOutputInformation:
            printm('获取Player操作信息。')
        
        #
        
        # 渲染顺序：
        # entity_around
        # MovBomb (Bomb_around + Bomb + bbs)
        # entity
        
        #
        
        
        for x in range(max(e1.x-1, 0), min(e1.x+2, 20)):
            for y in range(max(e1.y-1, 0), min(e1.y+2, 15)):
                draw_block(x, y, Map[y][x])
        for x in range(max(e2.x-1, 0), min(e2.x+2, 20)):
            for y in range(max(e2.y-1, 0), min(e2.y+2, 15)):
                draw_block(x, y, Map[y][x])
        for x in range(max(e3.x-1, 0), min(e3.x+2, 20)):
            for y in range(max(e3.y-1, 0), min(e3.y+2, 15)):
                draw_block(x, y, Map[y][x])
        for x in range(max(pl.x-1, 0), min(pl.x+2, 20)):
            for y in range(max(pl.y-1, 0), min(pl.y+2, 15)):
                draw_block(x, y, Map[y][x])
        
        MovBomb(pl, e1, e2, e3, isOnlyRender = True)
        if ftps() >= MovIceThornTps:
            movIceThorn(tuple([pl, e1, e2, e3]), False)
            MovIceThornTps = ftps() + 50
        else:
            movIceThorn(tuple([pl, e1, e2, e3]), isOnlyRender = True)
        pl.mov_effect()
        if TNTList != []:
            for t in TNTList:
                mods.Iris.draw_item(t)
        
        if first_run == True and not mods.cfg.SimplifyOutputInformation:
            printm('地图更新完成。')
        
        if Title_Bar[0] != None:
            mods.printlib.TitleBarPrint(Title_Bar[0])
            for x in range(5, 15):
                for y in range(6, 12):
                    draw_block(x, y, Map[y][x])
            if ftps() > Title_Bar[1]:
                Title_Bar[0] = None
                Redraw()
        
        if ftps() >= e1.nextTps:
            e1.run(pl, power_max, e2, e3)
        if e1.health > 0:
            mods.Iris.draw_entity(e1, screen)
        if ftps() >= e2.nextTps:
            e2.run(pl, power_max, e1, e3)
        if e2.health > 0:
            mods.Iris.draw_entity(e2, screen)
        if ftps() >= e3.nextTps:
            e3.run(pl, power_max, e1, e2)
        if e3.health > 0:
            mods.Iris.draw_entity(e3, screen)
        if first_run and not mods.cfg.SimplifyOutputInformation:
            printm('获取NPC信息。')
        if pl.health > 0:
            mods.Iris.draw_entity(pl, screen)
        if first_run == True:
            if not mods.cfg.SimplifyOutputInformation:
                printm('绘制完成。')
            printm('循环检查完成。')
            first_run = False
        pygame.display.update()
        
        

def normal():
    Ellipsis
    #global screen
    #while True:
    #    fps.tick(102)

def hard():
    Ellipsis
    #global screen
    #while True:
    #    fps.tick(102)

#1

Hello_text = ['Hello world!', 'Also try TwilightForest?', 'Happy happy happy!', 'Do you love fire and light?']
f1=pygame.freetype.Font(None,0x16)
freeRect = f1.render_to(screen, (720, 500), rd.choice(Hello_text),
                        fgcolor = mods.CrystalLib.RandomColor(), rotation=35)
if mods.cfg.EnableVerticalSynchronization == True:
    pygame.display.set_mode(vsync = True)
printm('Success loading base.')
printm('成功进入主循环。')

#while True:
#    fps.tick(10)
#    

def Main():
    global WARN_TOTAL
    try:
        reLoad()
        printm('地图初始化完成。')
        bedwar()
    except ExitGame as e:
        printm(f'退出游戏: {e}.')
    except Exception:
        WARN_TOTAL -= 1
        print_warning(f'A serious Exception occured: \n{traceback.format_exc()}')
        pygame.time.wait(10_000)
    finally:
        return

Start_Screen_Text = f.render('Press R to start new game.', True, (0,0,255))
Start_Screen_Text_2 = f.render(f'{_MODS_COUNT_} mods loaded.', True, (0,0,255))
def start_main():
    pygame.display.set_mode((1500, 900), vsync = mods.cfg.EnableVerticalSynchronization)
    HelloText = rd.choice(Hello_text)
    while True:
        fps.tick(10)
        pygame.draw.rect(screen, (255,255,0xff), (0,0,1199, 900))
        screen.blit(Start_Screen_Text, (450, 450))
        screen.blit(Start_Screen_Text_2, (450, 480))
        if NewVersionTip.isNewTry == True:
            #New_version_text = f.render(NewVersionTip.string, True, (0, 255, 0))
            #screen.blit(New_version_text, (450, 520))
            mods.printlib.OutTextxy(NewVersionTip.string, color = (0, 255, 0), place = ('center', 2))
        
        f1.render_to(screen, (820, 210), HelloText,fgcolor = mods.CrystalLib.RandomColor(), rotation=30)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                return
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_r:
                    Main()
                    HelloText = rd.choice(Hello_text)
                elif event.key == pygame.K_c:
                    mods.cfg.change_config(screen)
            
        pygame.display.flip()
start_main()
#os.system('Pause')
pygame.quit()
printm('关闭图形渲染窗口。')

printm('服务器连接已断开。')
os.system('Pause')